import multiprocessing
import os
import shlex
import signal
import subprocess
import sys
from argparse import ArgumentParser
from time import sleep, time
from multiprocessing import Process


from pydub import AudioSegment

from pydub.playback import play
from pydub.utils import mediainfo
from moviepy.editor import VideoFileClip


def get_audio_duration(f):
    return float(mediainfo(f)['duration'])


def get_video_duration(f):
    clip = VideoFileClip(f)
    clip.close()
    return clip.duration


class VideoRecoder:
    def __init__(self, f: str, preview=False) -> None:
        assert f.endswith('.mp4')
        if sys.platform == 'linux':
            format = 'v4l2'
            device = '/dev/video0'
        elif sys.platform == 'win32':
            format = 'dshow'
            device = '0'
        elif sys.platform == 'darwin':
            format = 'avfoundation'
            device = 'default'
        else:
            raise NotImplementedError(
                'Unsupported platform: {}'.format(format))

        args = [
            ['-f', format],
            ['-framerate', '30'],
            ['-i', device],
            ['-s', '640x480'],
            ['-c:v', 'libx264'],
            # ['-preset', 'veryfast'],
            ['-crf', '18'],
        ]
        if preview:
            args.extend([
                ['-map', '0'],
                ['-f', 'tee'],
                ['"{}|[f=nut]pipe:"'.format(f)],
                ['|', 'ffplay', 'pipe:']
            ])
        else:
            args.append([f])

        cmd = ['ffmpeg', '-y']
        for arg in args:
            # cmd += '{} {} '.format(arg[0], arg[1])
            cmd.extend(arg)
        print(' '.join(cmd))
        self.cmd = ' '.join(cmd)

    def start(self):
        def run():
            os.system(' '.join(self.cmd))
        self.sub_process = subprocess.Popen(
            self.cmd, shell=True, stdin=subprocess.PIPE)

    def close(self):
        self.sub_process.communicate(b'q')
        self.sub_process.wait()


parser = ArgumentParser()
parser.add_argument('-a', type=str, default='/media/yiwei/yiwei-01/project/pengfei/Data/audio/sifan.mp3')
parser.add_argument('-o', type=str, default='/media/yiwei/yiwei-01/project/pengfei/Data/video')
parser.add_argument('--preview', action='store_true', default=False)

args = parser.parse_args()
print(args)

name = os.path.basename(args.a)
name, _ = os.path.splitext(name)
out_video_tmp = os.path.join(args.o, '{}_tmp.mp4'.format(name))
out_video = os.path.join(args.o, '{}.mp4'.format(name))


song = AudioSegment.from_mp3(args.a)
cap = VideoRecoder(out_video_tmp, preview=args.preview)

input('Enter 开始录制')
cap.start()
play(song)
cap.close()


# align video and audio
audio_duration = get_audio_duration(args.a)
video_duration = get_video_duration(out_video_tmp)

offset = video_duration - audio_duration
print('offset:', offset)

if offset > 0:
    os.system('ffmpeg -y -i {} -itsoffset {} -i {} {}'.format(
        args.a, -offset, out_video_tmp, out_video
    ))
else:
    os.system('ffmpeg -y -itsoffset {} -i {}  -i {}  {}'.format(
        offset, args.a, out_video_tmp, out_video
    ))

os.remove(out_video_tmp)
